#!/usr/bin/env python

# -*- coding: utf-8 -*

"""
引脚
"""

import RPi.GPIO as GPIO
import logging


class Pin:
    """
    GPIO引脚
    """

    gpioMode = GPIO.BOARD
    """GPIO模式"""

    id: int
    """引脚编号"""

    pinMode = GPIO.OUT
    """引脚类型，是输入(GPIO.IN)还是输出(GPIO.OUT)"""

    description: str
    """引脚描述，比如'左前轮'"""

    initValue: float = None
    """初始化时设置的值"""

    resetValue: float = None
    """重置时设置的值"""

    nowValue: float = initValue
    """当前引脚的值"""

    def __init__(self, id, pinMode, gpioMode = GPIO.getmode(), description = "") -> None:
        self.id = id
        self.pinMode = pinMode
        self.gpioMode = gpioMode
        self.description = description
        logging.debug(f"GPIO 构造方法，引脚编号：{id}，引脚模式：{pinMode}，GPIO模式：{gpioMode}，描述：{description}")

    def initGpioPin(self) -> None:
        """初始化GPIO引脚"""
        if self.initValue is None:
            GPIO.setup(self.id, self.pinMode)
            logging.debug(f"GPIO初始化，引脚编号：{self.id}，引脚模式：{self.pinMode}")
        else:
            GPIO.setup(self.id, self.pinMode, initial = self.initValue)
            logging.debug(f"GPIO初始化，引脚编号：{self.id}，引脚模式：{self.pinMode}，初始值：{self.initValue}")

    def reset(self) -> bool :
        """重置状态"""
        if self.resetValue is None:
            logging.warning(f"引脚{self.id}未设置重置值，无法重置")
            return False
        if not self.writeable():
            logging.warning(f"引脚{self.id}不是输出模式，无法重置")
            return False
        self.write(self.resetValue)
        logging.debug(f"GPIO重置，引脚编号：{self.id}，重置值：{self.resetValue}")
        return True
    
    def cleanup(self) -> None:
        GPIO.cleanup(self.id)
        logging.debug(f"GPIO清理，引脚编号：{self.id}")

    def readable(self) -> bool:
        """引脚是否可读"""
        return self.pinMode == GPIO.IN

    def read(self, noLog = False):
        """读取引脚数据"""
        if not self.readable():
            raise f"引脚{self.id}的模式不是输入模式，无法读取数据"
        v = GPIO.input(self.id)
        if not noLog:
            logging.debug(f"GPIO读取数据，引脚编号：{self.id}，数据：{v}")
        return v

    def writeable(self) -> bool:
        """引脚是否可写"""
        return self.pinMode == GPIO.OUT

    def write(self, value, noLog = False) -> None:
        """写入引脚数据"""
        if not self.writeable():
            raise f"引脚{self.id}的模式不是输出模式，无法写入数据"
        oldValue = self.nowValue
        try:
            self.nowValue = value
            if not noLog:
                logging.debug(f"GPIO写入数据，引脚编号：{self.id}，数据：{value}，之前的数据：{oldValue}")
            return GPIO.output(self.id, value)
        except:
            self.nowValue = oldValue
            logging.warning(f"引脚{self.id}写入数据失败，旧数据：{oldValue}，新数据：{value}")

    def writeLow(self) -> None:
        self.write(GPIO.LOW)
    
    def writeHigh(self) -> None:
        self.write(GPIO.HIGH)
